<template>
  <a-spin :loading="loading">
    <template v-if="!wildCard">
      <a-alert v-if="applying"> 证书申请中，请耐心等待 </a-alert>
      <template v-else>
        <LicenseInfo v-if="hasLicenseInfo" :source="2" />
        <div v-else class="upload">
          <i-icons-no-cert />
          <span class="text-3">
            当前无证书，您可以
            <span class="text-primary cursor-pointer" @click="applyLicense">
              申请证书
            </span>
          </span>
        </div>
      </template>
      <a-button
        v-if="isExpired || applyFailed"
        status="normal"
        type="text"
        class="px-4! mt-2 w-fit"
        @click="applyLicense">
        重新申请
      </a-button>
    </template>
    <template v-else>
      <div class="mode-two">
        <span class="subtitle">
          请前往域名
          {{ siteStore.siteInfo.domain }}
          对应的DNS服务商为域名添加如下解析记录，添加成功后请勿删除或修改
        </span>
        <a-table :data="data" :columns="columns" :pagination="false">
          <template #type="{ record }">
            <span class="font-bold">{{ record.type }}</span>
          </template>
        </a-table>

        <div class="flex">
          <a-button
            status="normal"
            type="text"
            class="px-4! w-fit"
            @click="verifyRecords">
            验证解析记录
          </a-button>
          <a-button
            v-if="showApplyBtn"
            status="normal"
            type="text"
            class="px-4! w-fit"
            :disabled="!verifyPass"
            @click="applyLicense">
            申请证书
          </a-button>
        </div>
        <a-alert v-if="verifyPass" type="success" class="mt-2">
          {{ verifySuccessText }}
        </a-alert>
        <a-alert v-else-if="!firstVerify && !verifyPass" type="error">
          验证失败，请检查配置，或稍后重试
        </a-alert>
        <a-alert v-if="applying">证书申请中，请耐心等待 </a-alert>
        <LicenseInfo
          v-if="!applying && hasLicenseInfo"
          :source="2"
          class="mt-4" />
      </div>
    </template>
  </a-spin>
</template>
<script lang="ts" setup>
import type { SiteLicenseCname } from '@/apis/model/License'
import {
  getApiCertApi,
  getApiCertLookupCnameApi,
  postApiCertObtainApi
} from '@/apis/modules/license'
import { LICENSE_APPLY_STATUS } from '@/constants'
import { useSiteStore } from '@/stores/site'
import { useIntervalFn } from '@vueuse/core'
import LicenseInfo from './LicenseInfo.vue'

const cname = defineModel<SiteLicenseCname>('cname', { required: true })
const licenseInfo = inject(licenseInfoKey)
const route = useRoute()
const loading = ref(false)
const siteStore = useSiteStore()
const siteId = computed(() => route.params.id as string)
const emit = defineEmits(['reload'])
// 首次验证
const firstVerify = ref(true)

// 解析记录验证是否通过
const verifyPass = ref<boolean>(false)

// 获取证书申请id是否存在
const hasLicenseId = computed(() => {
  return (
    Number(licenseInfo?.value?.site_cert?.platform_cert_id) > 0 ||
    Number(licenseInfo?.value?.platform_cert?.id) > 0
  )
})

// 有id或错误消息视为有证书申请信息
const hasLicenseInfo = computed(
  () => hasLicenseId.value || licenseInfo?.value?.platform_cert?.error_msg
)

// 申请结果
const applyResult = ref<LICENSE_APPLY_STATUS>()

// 是否为泛域名
const wildCard = computed(() => siteStore.siteInfo.domain.startsWith('*'))

// 是否处于申请中状态
const applying = computed(() => {
  return applyResult.value === LICENSE_APPLY_STATUS.APPLYING
})

// 申请失败
const applyFailed = computed(() => {
  return applyResult.value === LICENSE_APPLY_STATUS.FAILED
})

// 展示申请按钮
const showApplyBtn = computed(() => {
  const id = Number(licenseInfo?.value?.site_cert?.platform_cert_id || '0') // 已经成功申请过证书
  if (applying.value) {
    return false
  }
  // 证书存在,且未过期
  if (id > 0 && !isExpired.value) {
    return false
  }

  return true
})

// 证书是否到期
const isExpired = computed(() => {
  const time1 = Math.floor(Date.now() / 1000)
  const time2 = licenseInfo?.value?.platform_cert?.expired_at ?? 0
  if (time2 > 0) {
    return time1 > time2
  }
  return false
})

const verifySuccessText = computed(() => {
  if (applying.value) return '验证通过'
  if (licenseInfo?.value?.site_cert?.platform_cert_id) {
    return isExpired.value ? '验证通过，可申请证书' : '验证通过'
  } else {
    return '验证通过，可申请证书'
  }
})
const columns = buildColumns([
  {
    title: '记录类型',
    slotName: 'type'
  },
  {
    title: '主机记录',
    dataIndex: 'name',
    format: 'copy'
  },
  {
    title: '记录值',
    dataIndex: 'target',
    format: 'copy'
  }
])
const data = computed(() => (cname.value ? [cname.value] : []))
const ApplyId = ref('') // 申请中或申请失败的证书id
const verifyRecords = () => {
  loading.value = true
  getApiCertLookupCnameApi({
    site_id: siteId.value,
    site_domain: siteStore.siteInfo.domain
  })
    .then((res) => {
      verifyPass.value = res.available ?? false
      if (verifyPass.value) {
        ToastUtils.success('验证通过')
      }
    })
    .finally(() => {
      firstVerify.value = false
      loading.value = false
    })
}
const applyLicense = () => {
  loading.value = true
  postApiCertObtainApi({ site_id: siteId.value })
    .then((res) => {
      ApplyId.value = res.id!
      applyResult.value = LICENSE_APPLY_STATUS.APPLYING
      resume()
      emit('reload', false)
    })
    .finally(() => {
      loading.value = false
    })
}
const { pause, resume } = useIntervalFn(
  () => {
    getApplyResult()
  },
  3000,
  {
    immediate: false
  }
)
function getApplyResult() {
  const id = ApplyId.value
    ? ApplyId.value
    : licenseInfo?.value?.platform_cert?.id ?? ''
  getApiCertApi({ id })
    .then((res) => {
      applyResult.value = res.apply_result ?? LICENSE_APPLY_STATUS.UNKNOWN
      if (applyResult.value !== LICENSE_APPLY_STATUS.APPLYING) {
        emit('reload', false)
        pause()
      }
    })
    .catch(() => {
      pause()
    })
}

watch(
  () => licenseInfo?.value,
  (v) => {
    if (v?.platform_cert?.apply_result) {
      applyResult.value = v.platform_cert?.apply_result
    }
  },
  {
    immediate: true
  }
)

onMounted(() => {
  if (applying.value) {
    resume()
  }
})
</script>
<style lang="less">
.upload {
  border: 1px dashed var(--color-border-4);
  @apply flex flex-col justify-center
      items-center p-4 gap-y-2;
}
.mode-two {
  border: 1px dashed var(--color-border-4);
  @apply flex flex-col 
       p-4 gap-y-2;
}
</style>
